package com.glodon.paas.databag.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.dozer.Mapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.glodon.paas.databag.api.bean.TaskDto;
import com.glodon.paas.databag.dao.DatabagRepository;
import com.glodon.paas.databag.dao.DatabagTaskRepository;
import com.glodon.paas.databag.model.Databag;
import com.glodon.paas.databag.model.DatabagTask;
import com.glodon.paas.databag.observer.DatabagObserver;
import com.glodon.paas.databag.service.TaskService;
import com.glodon.paas.exception.PaasServerExceptionFactory;
import com.glodon.paas.job.model.TaskStatus;

@Service
public class TaskServiceImpl implements TaskService {
    private final Logger logger = LoggerFactory.getLogger(TaskServiceImpl.class);

    @Autowired
    private Mapper mapper;
    @Autowired
    private DatabagTaskRepository databagTaskRepository;
    @Autowired
    private DatabagRepository databagRepository;
    @Autowired
    private List<DatabagObserver> observers = new ArrayList<DatabagObserver>();

    @Override
    @Transactional
    public boolean onTaskNotify(TaskDto task) {
        logger.info("receive job-server task notify:{}", task);
        List<DatabagTask> tasks = databagTaskRepository.findByTaskId(task.getTaskId());
        if (tasks == null || tasks.isEmpty()) {
            logger.error("invalid taskId:" + task.getTaskId());
            return false;
        }
        databagTaskRepository.modifyPkgTaskProgress(task.getTaskId(), mapper.map(task, DatabagTask.class));
        if (TaskStatus.success.equals(task.getStatus()) || TaskStatus.failure.equals(task.getStatus())
                || TaskStatus.canceled.equals(task.getStatus())) {
            Databag databag = databagRepository.findOne(tasks.get(0).getDatabagId());
            // job.setOutput(task.getOutput());
            databag.setEndTime(new Date());
            databag.setSuccess(TaskStatus.success.equals(task.getStatus()));
            databagRepository.save(databag);

            notifyObserver(task, databag);

            return true;
        } else {
            return false;
        }
    }

    /**
     * 通知数据包的观察者.
     * 
     * @param task
     * @param databag
     */
    private void notifyObserver(TaskDto task, Databag databag) {
        if (observers == null && observers.isEmpty()) {
            return;
        }
        if (TaskStatus.success.equals(task.getStatus())) {
            for (DatabagObserver observer : observers) {
                try {
                    observer.onSuccess(databag);
                } catch (Throwable t) {
                    logger.error("error occurs when invoking databag observer.", t);
                }
            }
        }
    }

    @Override
    public TaskDto getTaskByDatabagId(String databagId) {
        List<DatabagTask> tasks = databagTaskRepository.findByDatabagId(databagId);
        if (!tasks.isEmpty()) {
            return mapper.map(tasks.get(0), TaskDto.class);
        } else {
            throw PaasServerExceptionFactory.notFoundException("invalid databagId:" + databagId, null);
        }
    }

    public void setDatabagJobRepository(DatabagRepository databagJobRepository) {
        this.databagRepository = databagJobRepository;
    }

    public void setDatabagTaskRepository(DatabagTaskRepository databagTaskRepository) {
        this.databagTaskRepository = databagTaskRepository;
    }

    public void setMapper(Mapper mapper) {
        this.mapper = mapper;
    }

    @Override
    public void setObservers(List<DatabagObserver> observers) {
        this.observers = observers;
    }

}
